07. Parameterized and Repeated Tests

Parameterized and Repeated Tests

ND079 JPND C3 L4 A06 Parameterized Tests V2

Parameterized Tests

You can expand your test coverage by using the @ParameterizedTest annotation to rerun the same test with different input parameters multiple times. This annotation is used in combination with an ArgumentsSource. The below example uses a @ValueSource to pass in individual values.

@ParameterizedTest
@ValueSource(ints = {1, 5, 100, 1000, 100000})
public void addTwoNumbers_addSix_returnsNumberPlusSix(int number) {
    int input1 = 6;
    int expected = number + 6;
    App app = new App();
    Assertions.assertEquals(expected, app.addTwoNumbers(number, input1));
}

CsvSource

You can provide multiple values at once using a @CsvSource, which accepts a list of Strings containing comma-delimited values. It will automatically attempt to parse this list and cast the values to primitive types.

@ParameterizedTest(name = "[{index}] {0} + {1} = {2}")
@DisplayName("Add 6 to normal numbers \uD83D\uDC04")
@CsvSource({
        "6, 5, 11",
        "6, 1, 7",
        "6, 100, 106",
        "6, 1000, 1006",
        "6, 100000, 100006"
})
public void addTwoNumbers_addSix_returnsNumberPlusSix(int input1, int input2, int expected) {
    App app = new App();
    Assertions.assertEquals(expected, app.addTwoNumbers(input1, input2));
}

MethodSource

You can also create an ArgumentsSource programmatically, using the annotation @MethodSource, which takes a single String parameter specifying the name of the method that should be used to provide Arguments.

@MethodSource("fancyArgumentProvider")    

For example, the above annotation would tell a @ParameterizedTest to use this method to provide its arguments:

private static Stream<Arguments> fancyArgumentProvider() {
    return Stream.of(
            Arguments.of(6, 5, 11),
            Arguments.of(6, 1, 7)
    );
}

EnumSource

Another kind of MethodSource iterates over all the members of an enum and passes them as an input parameter to your test.

enum SomeNumber {
    ONE(1), FIVE(5), ONE_HUNDRED(100);
    int number;
    SomeNumber(int number) { this.number = number; }
    public int getNumber() { return this.number;}
}

@ParameterizedTest
@EnumSource(SomeNumber.class)
public void addTwoNumbers_addSixEnum_returnsValuePlusSix(SomeNumber num) {
    App app = new App();
    int expected = switch(num) {
        case ONE -> 7;
        case FIVE -> 11;
        case ONE_HUNDRED -> 106;
        default -> 0;
    };
    Assertions.assertEquals(expected, app.addTwoNumbers(6, num.getNumber()));
}

Repeated Tests

ND079 JPND C3 L4 A07 Repeated Tests V3

Repeated Test Annotation

To rerun the same test multiple times, you can use the @RepeatedTest annotation. It takes a single parameter specifying the number of iterations, and allows you to pass an optional parameter to your test method called RepetitionInfo.

For example, this method tests the numbers 1-10.

    @RepeatedTest(10)
    public void addTwoNumbers_addSix_returnsValuePlusSix(RepetitionInfo repetitionInfo) {
        int input1 = repetitionInfo.getCurrentRepetition();
        int input2 = 6;
        int expected = 6 + input1;
        App app = new App();
        Assertions.assertEquals(expected, app.addTwoNumbers(input1, input2));
    }

You might use @RepeatedTest to:

  • Verify actions can be executed multiple times with the same result
  • Identify infrequent errors
  • Informal performance evaluation